package handler

import (
	"encoding/json"
	"fmt"
	"gitee.com/sansaniot/ssiot-core/facade/env"
	"gitee.com/sansaniot/ssiot-core/httpmvc"
	"gitee.com/sansaniot/ssiot-core/httpmvc/api"
	"github.com/gin-gonic/gin"
	"ssadmin/common/constant"
	"ssadmin/common/utils"
	"ssadmin/internal/admin/models"
	"ssadmin/internal/admin/models/command"
	"ssadmin/internal/admin/service"
	globalUtil "ssadmin/internal/admin/utils"
)

func AuthenticatorFromAccount(c *gin.Context) (interface{}, error) {
	log := api.GetRequestLogger(c)
	db, err := httpmvc.GetOrm(c)
	tenant := c.GetHeader(constant.CacheKeyTenant)
	tenant = "public"

	var loginVals LoginUser
	if err = c.ShouldBind(&loginVals); err != nil {
		loginVals.Username, _ = c.GetPostForm("username")
		loginVals.Password, _ = c.GetPostForm("password")
		loginVals.Phone, _ = c.GetPostForm("phone")
		loginVals.Code, _ = c.GetPostForm("code")
		loginVals.WxCode, _ = c.GetPostForm("wxCode")
	}

	loginVals.Tenant = tenant
	var userInfo models.User
	var errMsg string
	var e error
	if len(loginVals.MpAppId) == 0 {
		loginVals.MpAppId = "wxb8d521a54076b5fe" //默认appId
	}
	if len(loginVals.Username) > 0 && len(loginVals.Password) > 0 {
		// 用户密码登录
		userInfo, e = loginVals.LoginUsername(db)
		if e != nil {
			c.Set("loginError", "用户名或密码错误")
			return nil, nil
		}
		// 校验密码
		errMsg = validPwd(c, loginVals, &userInfo)
	} else if len(loginVals.Phone) > 0 && len(loginVals.Code) > 0 {
		//校验验证码
		passwdForgetReq := command.PasswordForgetResetReq{
			Code:   loginVals.Code,
			Mobile: loginVals.Phone,
		}
		vs := service.VerifyCode{}
		if validErr := vs.ValidCode(&passwdForgetReq); validErr != nil {
			c.Set("loginError", "验证码过期或者无效")
			return nil, nil
		}
		// 手机号验证码登录
		userInfo, e = loginVals.LoginUserPhone(db)
		if e != nil || len(userInfo.UserId) == 0 {
			e = nil
			// 手机号不存在则注册
			register := service.Register{}
			register.Orm = db
			registerReq := command.RegisterInsertReq{}
			registerReq.Mobile = loginVals.Phone
			registerReq.Code = loginVals.Code
			registerReq.UserName = loginVals.Phone
			registerReq.Password = "123456"
			registerReq.Company = loginVals.Phone + "的公司"
			register.Insert(&registerReq)

		}
		//再次获取手机用户
		userInfo, e = loginVals.LoginUserPhone(db)
		if e != nil {
			// 手机号不存在 注册失败
			c.Set("loginError", "手机号或验证码错误")
			return nil, nil
		}
		// 存在wxCode 则绑定
		if len(loginVals.WxCode) > 0 {
			wx := &service.UserWX{}
			wx.Orm = db
			userWeixin := command.UserWeixin{}
			userWeixin.Code = loginVals.WxCode
			userWeixin.Phone = loginVals.Phone
			userWeixin.MpAppId = loginVals.MpAppId

			user := models.User{}
			//openId := wx.GetOpenid(loginVals.WxCode, "wxb8d521a54076b5fe")
			wxError := wx.BindByPhone(&userWeixin, &user)
			if wxError != nil {
				log.Error(wxError)
				c.Set("loginError", "绑定微信失败")
				return nil, nil
			}
		}
		//成功后删除验证码
		cacheKey := fmt.Sprintf("%s%s", constant.PrefixAuthCode, loginVals.Phone)
		env.Cache.Del(cacheKey)
	} else if len(loginVals.WxCode) > 0 {
		//校验code 获取openID
		wx := &service.UserWX{}
		wx.Orm = db
		openId := wx.GetOpenid(loginVals.WxCode, "wxb8d521a54076b5fe")
		// 校验OpenId是否存在
		if len(openId) == 0 {
			c.Set("loginError", "code不合法")
			return nil, nil
		}
		loginVals.OpenId = openId
		// 校验OpenId是否存在
		userInfo, e = loginVals.LoginUserOpenId(db)
		if e != nil || len(userInfo.UserId) == 0 {
			c.Set("loginError", "openId未找到")
			return nil, nil
		}
	} else if len(loginVals.QrCode) > 0 {
		cacheKey := fmt.Sprintf("%s%s", constant.PrefixQrCodeInfo, loginVals.QrCode)
		data, _ := env.Cache.Get(cacheKey)
		if len(data) == 0 {
			c.Set("loginError", "二维码无效")
			return nil, nil
		}
		m := make(map[string]interface{})
		_ = json.Unmarshal([]byte(data), &m)
		if m["username"] != nil {
			loginVals.Username = m["username"].(string)
			userInfo, e = loginVals.LoginUsername(db)
			if e != nil {
				c.Set("loginError", "登录用户不存在")
				return nil, nil
			}
		} else {
			c.Set("loginError", "二维码登录失败")
			return nil, nil
		}
	} else {
		c.Set("loginError", "登录请求参数异常")
		return nil, nil
	}
	defer func() {
		LoginLogToDB(c, "用户登录", userInfo)
	}()

	if len(errMsg) > 0 {
		log.Warn(errMsg)
		c.Set("loginError", errMsg)
		return nil, nil
	}

	//设置用户信息缓存
	_ = loginVals.GetProfile(db, &userInfo)
	userInfo.Tenant = tenant
	profile := map[string]interface{}{
		constant.CacheKeyUserDeptIds:  userInfo.DeptIds,
		constant.CacheKeyUserDeptName: userInfo.DeptName,
		constant.CacheKeyUserRoleIds:  userInfo.RoleId,
		constant.CacheKeyAgencyId:     userInfo.Agency,
		constant.CacheKeyUserId:       userInfo.UserId,
		constant.CacheKeyUserName:     userInfo.Username,
		constant.CacheKeyCreator:      userInfo.Creator,
		constant.CacheKeyCreatorId:    userInfo.CreatorId,
		constant.CacheKeyAvatar:       userInfo.Avatar,
		constant.CacheKeyAlias:        userInfo.Alias,
	}
	globalUtil.SetUserProfile(userInfo.Username, profile)
	c.Set(constant.CacheKeyUserInfo, profile)
	return userInfo, nil
}

func validPwd(c *gin.Context, loginVals LoginUser, user *models.User) string {
	var inputPwd, decodePwd string
	aesKey := "aes" + c.GetHeader("authtimestamp")

	//先解密
	decodePwd, err := utils.AesDecrypt(loginVals.Password, aesKey)
	if err != nil {
		return "密码错误"
	}
	inputPwd = utils.Md5Pwd(decodePwd, loginVals.Username+decodePwd)

	if inputPwd != user.Password {
		return "用户名或密码错误！"
	}

	if "0" == user.Status {
		return "账号已被锁定,请联系管理员！"
	}
	return ""
}
